using Pegasus.Monitoring;
using System;
using System.Collections;

namespace Pegasus.Diagnostics
{
	/// <summary>
	/// The method timer class is used to time a given operation.
	/// </summary>
	public class OperationTimer : IDisposable
	{
		// Local Instance Values
		private int m_startTicks = Environment.TickCount;
		private int m_stopTicks = -1;
		private bool m_running = true;

		/// <summary>
		/// Constructor used for tracking distributed calls.
		/// </summary>
		public OperationTimer()
		{
		}

		/// <summary>
		/// The number of cpu ticks that the method has taken. If the timer is still
		/// running then it returns the about of time since the timer started.
		/// If the timer has been stopped then it is the amount of time the method
		/// or operation took. 
		/// </summary>
		public virtual int Ticks
		{
			get
			{
				if( m_running )
				{
					return Environment.TickCount - m_startTicks;
				}

				return m_stopTicks - m_startTicks;
			}
		}

        /// <summary>
        /// 
        /// </summary>
        public long Milliseconds
        {
            get
            {
                if( m_running )
                {
                    return GetTickDiffInMilliseconds( m_startTicks, Environment.TickCount );
                }
                return GetTickDiffInMilliseconds( m_startTicks, m_stopTicks );
            }
        }

		/// <summary>
		/// The amount of time that the method has taken. If the timer is still
		/// running then it returns the about of time since the timer started.
		/// If the timer has been stopped then it is the amount of time the method
		/// or operation took. 
		/// </summary>
		public virtual double Seconds
		{
			get
			{
				if( m_running )
				{
					return GetTickDiffInSeconds( m_startTicks, Environment.TickCount );
				}

				return GetTickDiffInSeconds( m_startTicks, m_stopTicks );
			}
		}

		/// <summary>
		/// Returns true if the timer is still running, other wise false;
		/// </summary>
		public virtual bool IsTimerRunning
		{
			get
			{
				return m_running;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public virtual void Dispose()
		{
			if( m_running )
			{
				Stop();
			}
		}

		/// <summary>
		/// Stops timing the call
		/// </summary>
		public virtual double Stop()
		{
			m_stopTicks = Environment.TickCount;
			m_running = false;
			
			return Seconds;
		}

        private long GetTickDiffInMilliseconds( int start, int stop )
        {
            long ticks;

            // Check for overflow
            if( start > stop )
            {
                ticks = ( long.MaxValue - start ) + stop;
            }
            else
            {
                ticks = stop - start;
            }

            return ticks;
        }

		/// <summary>
		/// Calculates the number of seconds between the start and stop values.
		/// </summary>
		/// <param name="start">The tick count at start</param>
		/// <param name="stop">The tick count at stop</param>
		/// <returns>The number of seconds.</returns>
		/// <remarks>
		/// This method takes into account the tick count register overflow
		/// </remarks>
		protected virtual double GetTickDiffInSeconds( int start, int stop )
		{
			int ticks;

			// Check for overflow
			if( start > stop )
			{
				ticks = ( Int32.MaxValue - start ) + stop;
			}
			else
			{
				ticks =  stop - start;
			}

			return (double) ( (double) ticks / 1000.0 );
		}
	}
}
